﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Spore.Utils
{
    public abstract class ThreadWorkManagerBase
    {
        private Thread workThread;
        protected AutoResetEvent waitResetEvent;
        protected AutoResetEvent stopReserEvent;
        private int idlesseWaitTime;
        private int startDelay;
        public int IdlesseWaitTime
        {
            get { return idlesseWaitTime; }
            set
            {
                if (value > 0)
                { this.idlesseWaitTime = value; }
            }
        }
        public int StartDelay
        {
            get { return startDelay; }
            set
            {
                if (value > 0)
                    this.startDelay = value;
            }
        }
        private volatile bool stop;
        private volatile bool exit;

        public ThreadWorkManagerBase()
        {
            this.workThread = new Thread(Work);
            this.IdlesseWaitTime = 1000;
            this.StartDelay = 0;
            this.stopReserEvent = new AutoResetEvent(false);
            this.waitResetEvent = new AutoResetEvent(false);
        }

        private void Work()
        {
            Thread.Sleep(this.StartDelay);
            while (!exit)
            {
                this.CheckStop();
                this.ExeWork();
            }
        }

        private void CheckStop()
        {
            if (!stop) return;
            stopReserEvent.Reset();
            stopReserEvent.WaitOne();
        }

        private void ExeWork()
        {
            var v = GetWorkExecuter();
            if (v == null)
            {
                this.waitResetEvent.Reset();
                this.waitResetEvent.WaitOne(this.IdlesseWaitTime);
            }
            else
            {
                v.ExeDele();
                this.EndExeWork(v);
            }
        }

        protected virtual void EndExeWork(ThreadWorkExecuter executer)
        {
            
        }

        protected abstract ThreadWorkExecuter GetWorkExecuter();

        public void Start()
        {
            this.exit = false;
            this.stop = false;
            this.stopReserEvent.Set();
            if ((this.workThread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
                this.workThread.Start();
            else if ((this.workThread.ThreadState & ThreadState.Aborted) == ThreadState.Aborted)
            {
                CreateAndStartWorkThread();
            }
            else if ((this.workThread.ThreadState & ThreadState.Stopped) == ThreadState.Stopped)
            {
                CreateAndStartWorkThread();
            }
            else if ((this.workThread.ThreadState & ThreadState.StopRequested) == ThreadState.StopRequested)
            {
                CreateAndStartWorkThread();
            }
            else if ((this.workThread.ThreadState & ThreadState.AbortRequested) == ThreadState.AbortRequested)
            {
                CreateAndStartWorkThread();
            }
           
        }

        public virtual void Stop()
        {
            this.stop = true;
        }

        public virtual void Exit()
        {
            this.exit = true;
            this.stop = false;
            this.stopReserEvent.Set();
        }

        private void CreateAndStartWorkThread()
        {
            this.workThread = new Thread(Work);
            this.workThread.IsBackground = true;
            this.workThread.Start();
        }
    }

}
